import * as vscode from 'vscode';
import * as fs from 'fs';
import { SemVer } from 'semver';
// We could use FileType from utils/filesystem.ts, but it's simpler this way.
export import FileType = vscode.FileType;
export import FileStat = vscode.FileStat;
import { OSType } from '../utils/platform';

export type ReadStream = fs.ReadStream;
export type WriteStream = fs.WriteStream;
export const IFileSystem = Symbol('IFileSystem');
export interface IFileSystem {

    fileExists(path: string): Promise<boolean>;
    readFile(filePath: string): Promise<string>;
    move(src: string, tgt: string): Promise<void>;
}

//= ==========================
// filesystem operations

// The low-level filesystem operations on which the extension depends.
export interface IRawFileSystem {
    pathExists(filename: string): Promise<boolean>;
    // Get information about a file (resolve symlinks).
    stat(filename: string): Promise<FileStat>;
    // Move the file to a different location (and/or rename it).
    move(src: string, tgt: string): Promise<void>;
    readText(filename: string): Promise<string>;
}
export interface IFileSystemUtils {

    readonly raw: IRawFileSystem;
    fileExists(filename: string): Promise<boolean>;

}

//= ==========================
// FS paths

// The low-level file path operations used by the extension.
export interface IFileSystemPaths {
    readonly sep: string;
    join(...filenames: string[]): string;
    dirname(filename: string): string;
    basename(filename: string, suffix?: string): string;
    normalize(filename: string): string;
    normCase(filename: string): string;
}

// Where to fine executables.
//
// In particular this class provides all the tools needed to find
// executables, including through an environment variable.
export interface IExecutables {
    delimiter: string;
    envVar: string;
}

export const IFileSystemPathUtils = Symbol('IFileSystemPathUtils');
// A collection of high-level utilities related to filesystem paths.
export interface IFileSystemPathUtils {
    readonly paths: IFileSystemPaths;
    readonly executables: IExecutables;
    readonly home: string;
    // Return true if the two paths are equivalent on the current
    // filesystem and false otherwise.  On Windows this is significant.
    // On non-Windows the filenames must always be exactly the same.
    arePathsSame(path1: string, path2: string): boolean;
    // Return the clean (displayable) form of the given filename.
    getDisplayName(pathValue: string, cwd?: string): string;
}

export type TemporaryFile = { filePath: string } & vscode.Disposable;

export interface ITempFileSystem {
    createFile(suffix: string, mode?: number): Promise<TemporaryFile>;
}
export const IPlatformService = Symbol('IPlatformService');
export interface IPlatformService {
    readonly osType: OSType;
    osRelease: string;
    readonly pathVariableName: 'Path' | 'PATH';
    readonly virtualEnvBinName: 'bin' | 'Scripts';

    // convenience methods
    readonly isWindows: boolean;
    readonly isMac: boolean;
    readonly isLinux: boolean;
    readonly is64bit: boolean;
    getVersion(): Promise<SemVer>;
}